;	Tested and working

;	Menu Hack
;	If co-op data has been loaded in multiplayer mode and the team hasn't warped,
;	enable warping to Gem Quarry (warping to Gem Quarry doesn't work; actually using
;	location 0x0010 instead) via L button
;	(If warping is done, set warpingDone + RDRAM_START + TRAINER_OFFSET (aka warpingDone)
;	to 0xDEADBEEF)
;	Begin C0DE segment
.long				0xC0DE0000
.long				0x00000000

LUI	S0,	0x800A		;
LBU	S0,	0x5060	(S0)	;S0 = menu mode byte
ORI	S1,	R0,	0x0001	;S1 = multiplayer mode value
LUI	S2,	0x800A		;S2 = 0x800A0000
BNE	S0,	S1,		Menu_Hack_Exit
NOP				;Don't do anything if not in multiplayer mode
LBU	S3,	0x4FD0	(S2)	;S3 = number of players
SB	S3,	0x325D	(S2)	;Force split screen in multi

LUI	S4,	%hi(saveLoaded + RDRAM_START + TRAINER_OFFSET)
LW	S5,	%lo(saveLoaded + RDRAM_START + TRAINER_OFFSET)	(S4)
				;Don't do anything if Co-Op data hasn't been loaded
ADDIU	S5,	S5,	-0x0001	;
BNEZ	S5,			Menu_Hack_Exit
LW	S5,	%lo(warpingDone + RDRAM_START + TRAINER_OFFSET)	(S4)
LUI	S6,		0xDEAD	;
ORI	S6,	S6,	0xBEEF	;Don't do anything if warping has been done
BEQ	S5,	S6,		Menu_Hack_Exit

LUI	S0,	0x8010		;
LH	S0,	0x5304	(S0)	;
ANDI	S0,	S0,	0x0020	;L button status in S0

LUI	S1,	%hi(lastKeys + RDRAM_START + TRAINER_OFFSET)
LH	S2,	%lo(lastKeys + RDRAM_START + TRAINER_OFFSET)	(S1)
				;Previous L button status in S2
SH	S0,	%lo(lastKeys + RDRAM_START + TRAINER_OFFSET)	(S1)
				;Update previous status

XORI	S2,	S2,	0x0020	;last_keys = ~last_keys
AND	S0,	S0,	S2	;keys_down = ~last_keys & keys

ORI	S3,	R0,	0x0001	;S3 = true

;	L newly pressed set to true
BEQZ	S0,			Menu_Hack_Exit
NOP
SH	S3,	%lo(LnewlyPressed + RDRAM_START + TRAINER_OFFSET)	(S1)
LUI	S3,		0xDEAD	;
ORI	S3,	S3,	0xBEEF	;
SW	S3,	%lo(warpingDone + RDRAM_START + TRAINER_OFFSET)	(S1)	;
				;Kill this code before it crashes the game

				Menu_Hack_Exit:
JR	RA			;
NOP

.align				3
.long				0xE0000000
.long				0x00000000
;	End C0DE segment

;	"If L newly pressed" part of code
.long				0xD1000000 + LnewlyPressed + TRAINER_OFFSET
.long				0x00000001
;	gameActive?
.long				0xD1000000 + gameActive + TRAINER_OFFSET
.long				0x00000001
;	ERROR: This writes 0xFF, or at least the 0x01 becomes 0xFF;
;	it must be changed back to 0x01 once (and only once) to keep the emulator
;	from crashing
.long				0x800A3294
.long				0x00000001
;	FIXME: 0x0110 (Gem Quarry) is more aesthetic but doesn't work,
;	but 0x0010 (cave on Goldwood) is an ugly starting point (although it does work)
;	NOTE: 0x0010 doesn't work very often in PJ 64, but 0x0016 (Walkway) and 0x0110 do
;	NOTE: 0x0016 works in Mupen as well, so switching to that
.long				0x810A3250
.long				0x00000016
;	Tell other code to fix bug
.long				0x82000000 + menuHackVars + TRAINER_OFFSET
.long				0xDEADBEEF
;	Set L as not pressed
.long				0x81000000 + LnewlyPressed + TRAINER_OFFSET
.long				0x00000000
.long				0xE0000000
.long				0x00000000
.long				0xE0000000
.long				0x00000000

;	Handle bug of previous code
.long				0xD2000000 + menuHackVars + TRAINER_OFFSET
.long				0xDEADBEEF
.long				0xD00A3294
.long				0x000000FF
.long				0x800A3294
.long				0x00000001
;	Have this code disable itself
.long				0x82000000 + menuHackVars + TRAINER_OFFSET
.long				0x00000000
.long				0xE0000000
.long				0x00000000
.long				0xE0000000
.long				0x00000000

;	If 0x80046158 == (instruction that's usually there)
;	Do 0x87 code type for enabling single player menu if and only if
;	mode is single player OR co-op warping has been done
;	Also stores location/region/planet to save area
.long				0xD2046158
LBU	T9,	0x4FC4	(T9)	;Original code
.long				0x87046158
.long				0x00000000
;	T0 is free
ADDIU	SP,	SP,	-0x000C	;Stack stuff
SW	S0,	0x0000	(SP)	;""
SW	S1,	0x0004	(SP)	;""
SW	S2,	0x0008	(SP)	;""
LUI	T0,	%hi(0x800A323C)	;
LHU	T0,	%lo(0x800A323C)	(T0)	;
				;[location]
ORI	S2,	R0,	0x0118	;Size of room data at 0x00CB3100
MFHI	S0			;
MFLO	S1			;
MULTU	T0,	S2		;
MFLO	S2			;S2 holds offset
MTHI	S0			;
MTLO	S1			;
LUI	S1,	%hi(0x801E6010)	;Save address
ORI	S1,	S1,	%lo(0x801E6010)	;
SH	T0,	%lo(0x00 + TRIBAL_CACHE)	(S1)	;
				;lastLocation
LUI	T0,	%hi(0xB0CB3100)	;
ORI	T0,	T0,	%lo(0xB0CB3100)	;
ADDU	S0,	T0,	S2	;Using data from ROM instead of what's cached in RAM -
				;apparently what's in the RAM could be wrong (which might
				;be due to doing single player mode stuff in multi)
LBU	S2,	0x0020	(S0)	;
SB	S2,	%lo(0x03 + TRIBAL_CACHE)	(S1)	;
				;lastPlanet
LBU	S2,	0x0102	(S0)	;
SB	S2,	%lo(0x02 + TRIBAL_CACHE)	(S1)	;
				;lastRegion
;	Enable menu when appropriate
LBU	T9,	0x4FC4	(T9)	;Original code
BEQZ	T9,			Menu_Hack_Enable_Return
NOP
LUI	S0,	%hi(warpingDone + RDRAM_START + TRAINER_OFFSET)
LW	S0,	%lo(warpingDone + RDRAM_START + TRAINER_OFFSET)	(S0)
LUI	S1,	0xDEAD		;
ORI	S1,	S1,	0xBEEF	;Warping done?
BEQL	S0,	S1,		MHE_Warping_Done
ORI	T9,	R0,	0x0000	;Single player menu enabled
				MHE_Warping_Done:
				Menu_Hack_Enable_Return:
LW	S0,	0x0000	(SP)	;Stack stuff
LW	S1,	0x0004	(SP)	;""
LW	S2,	0x0008	(SP)	;""
ADDIU	SP,	SP,	0x000C	;""
J				0x0004615C
NOP
.align				3
.long				0xE0000000
.long				0x00000000
.long				0xE0000000
.long				0x00000000
;	End of Menu Hack
